package com.xqboss.apps.service.user;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xqboss.apps.constant.YeepayConfig;
import com.xqboss.apps.domain.consumer.ConsumerRealName;
import com.xqboss.apps.domain.user.YeepayWallet;
import com.xqboss.apps.dto.order.YeePayDivideDto;
import com.xqboss.apps.enums.order.DivideStatusEnum;
import com.xqboss.apps.mapper.user.YeepayWalletMapper;
import com.xqboss.apps.service.consumer.ConsumerRealNameService;
import com.xqboss.common.core.domain.entity.SysUser;
import com.xqboss.common.exception.ServiceException;
import com.xqboss.common.utils.uuid.IdUtils;
import com.yeepay.yop.sdk.model.YopRequestConfig;
import com.yeepay.yop.sdk.service.common.request.YopRequest;
import com.yeepay.yop.sdk.service.common.response.YopResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class YeepayWalletService extends ServiceImpl<YeepayWalletMapper, YeepayWallet> {

    @Autowired
    private YeepayConfig yeepayConfig;
    @Autowired
    private ConsumerRealNameService consumerRealNameService;


    /**
     * 获取用户的易宝钱包信息
     * @param userId
     * @return
     */
    public YeepayWallet getUserWallet(Long userId){
        YeepayWallet wallet = getById(userId);
        return wallet;
    }

    /**
     * 创建钱包回调
     */
    public void createWalletCallback(String bizData){
        JSONObject json = JSON.parseObject(bizData);
        String businessNo = json.getString("businessNo");
        String merchantNo = json.getString("merchantNo");
        String merchantUserNo = json.getString("merchantUserNo");
        String walletUserNo = json.getString("walletUserNo");
        String walletCategory = json.getString("walletCategory");

        YeepayWallet wallet = new YeepayWallet();
        wallet.setUserId(Long.valueOf(merchantUserNo.replace(yeepayConfig.getUserPrefix(), "")));
        wallet.setYpUserId(merchantUserNo);
        wallet.setMemberNo(walletUserNo);
        wallet.setWalletCategory(walletCategory);
//        wallet.setWalletStatus();
//        wallet.setRenewStatus();
//        wallet.setAgreementStatus();
        saveOrUpdate(wallet);
    }

    /**
     * 创建钱包
     *
     * @return
     */
    public String getWalletIndex(SysUser user){
        ConsumerRealName realName = consumerRealNameService.requireRealName(user.getUserId());
        YopRequest request = new YopRequest("/rest/v2.0/m-wallet/wallet/index","POST");
        YopRequestConfig requestConfig = request.getRequestConfig();

        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantUserNo", yeepayConfig.getUserPrefix() + user.getUserId());	//平台侧用户钱包id  必填
        request.addParameter("name", realName.getIdCardName());			//必填
        request.addParameter("certificateType", "IDENTITY_CARD");	//必填
        request.addParameter("certificateNo", realName.getIdCard());   //必填
        request.addParameter("mobile", user.getPhonenumber());//必填
        request.addParameter("returnUrl", yeepayConfig.getCreateWalletReturnUrl());
        request.addParameter("requestNo", IdUtils.fastSimpleUUID());
        request.addParameter("notifyUrl", yeepayConfig.getCreateWalletNotifyUrl());

        YopResponse response = yeepayConfig.getClient().request(request);
        Map<String, String> ret = (Map<String, String>) response.getResult();
        getUserWallet(user);
        return ret.get("url");
    }



    /**
     * 获取用户钱包信息
     *
     * @return
     */
    public String getUserWallet(SysUser user){
        YopRequest request = new YopRequest("/rest/v1.0/m-wallet/member/query","GET");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("externalUserId", yeepayConfig.getUserPrefix() + user.getUserId());

        YopResponse response = yeepayConfig.getClient().request(request);
        Map<String, String> ret = (Map<String, String>) response.getResult();
        return ret.get("memberNo");
    }


    /**
     * 验证是否开通钱包
     * @param userId
     */
    public void requireWallet(Long userId){
        if(getById(userId) == null){
            throw new ServiceException("您还未开通易宝钱包！");
        }
    }


    /**
     * 发起订单分账
     * @param param
     * @return
     */
    public void divideApply(YeePayDivideDto param) {
        YopRequest request = new YopRequest( "/rest/v1.0/divide/apply", "POST");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("orderId", param.getOrderNo());
        request.addParameter("uniqueOrderNo", param.getOutTradeNo());
        request.addParameter("divideRequestId", yeepayConfig.getUserPrefix()+param.getRequestId());
        Map<String, String> divideDetail = new HashMap<>();
        divideDetail.put("ledgerNo", param.getMemberNo());
        divideDetail.put("amount", param.getAmount().toPlainString());
        divideDetail.put("ledgerType", "MERCHANT2MEMBER");
        List<Map<String, String>> list = new ArrayList<>();
        list.add(divideDetail);
        request.addParameter("divideDetail", com.alibaba.fastjson2.JSON.toJSONString(list));
        try {
            YopResponse response = yeepayConfig.getClient().request(request);
            com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSON.parseObject(response.getStringResult());
            if ("OPR00000".equalsIgnoreCase(json.getString("code"))) {
                if ("SUCCESS".equalsIgnoreCase(json.getString("status"))) {
                    param.setStatus(DivideStatusEnum.SUCCESS);
                    param.setRemark(json.getString("divideDetail"));
                } else if ("PROCESSING".equalsIgnoreCase(json.getString("status"))) {
                    param.setStatus(DivideStatusEnum.PROCESSING);
                } else {
                    // 分账失败
                    param.setStatus(DivideStatusEnum.FAIL);
                    param.setRemark(json.getString("message"));
                    log.error("易宝分账失败! {} - {}", param.getOrderId(), response.getStringResult());
                }
            } else if ("OPR21016".equalsIgnoreCase(json.getString("code"))) {
                // 需要5秒后重试一次
                if (param.getRetryCount() != 0) {
                    param.setStatus(DivideStatusEnum.FAIL);
                    param.setRemark(response.getStringResult());
                    log.error("易宝分账请求失败! {} - {}", param.getOrderId(), response.getStringResult());
                } else {
                    Thread.sleep(5000);
                    param.setRetryCount(param.getRetryCount() + 1);
                    param.setRequestId(IdUtils.fastSimpleUUID());
                    divideApply(param);
                }
            } else {
                param.setStatus(DivideStatusEnum.FAIL);
                param.setRemark(response.getStringResult());
                log.error("易宝分账请求失败! {} - {}", param.getOrderId(), response.getStringResult());
            }
        } catch (Exception e) {
            param.setStatus(DivideStatusEnum.FAIL);
            param.setRemark("系统异常："+e.getMessage());
            log.error("易宝分账请求异常! {}", param.getOrderId(), e);
        }
    }

    /**
     * 查询分账结果
     * @param param
     * @return
     */
    public void divideQuery(YeePayDivideDto param) {
        YopRequest request = new YopRequest( "/rest/v1.0/divide/query", "GET");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("orderId", param.getOrderNo());
        request.addParameter("uniqueOrderNo", param.getOutTradeNo());
        request.addParameter("divideRequestId", yeepayConfig.getUserPrefix()+param.getRequestId());
        try {
            YopResponse response = yeepayConfig.getClient().request(request);
            com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSON.parseObject(response.getStringResult());
            if ("OPR00000".equalsIgnoreCase(json.getString("code"))) {
                if ("SUCCESS".equalsIgnoreCase(json.getString("status"))) {
                    param.setStatus(DivideStatusEnum.SUCCESS);
                } else {
                    log.error("易宝分账查询失败! {} - {}", param.getOrderId(), response.getStringResult());
                }
            } else {
                log.error("易宝分账查询请求失败! {} - {}", param.getOrderId(), response.getStringResult());
            }
        } catch (Exception e) {
            log.error("易宝分账查询请求异常! {}", param.getOrderId(), e);
        }
    }

    /**
     * 完成分账
     * @param param
     * @return
     */
    public void divideComplete(YeePayDivideDto param) {
        YopRequest request = new YopRequest( "/rest/v1.0/divide/complete", "POST");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("orderId", param.getOrderNo());
        request.addParameter("uniqueOrderNo", param.getOutTradeNo());
        request.addParameter("divideRequestId", yeepayConfig.getUserPrefix()+param.getRequestId());
        try {
            YopResponse response = yeepayConfig.getClient().request(request);
            com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSON.parseObject(response.getStringResult());
            if ("OPR00000".equalsIgnoreCase(json.getString("code"))) {
                if ("SUCCESS".equalsIgnoreCase(json.getString("status")) || "SUCCESS".equalsIgnoreCase(json.getString("divideStatus"))) {
                    param.setCompleteTime(new Date());
                    param.setStatus(DivideStatusEnum.COMPLETE);
                } else {
                    param.setRemark(json.getString("message"));
                    log.error("易宝分账完结失败! {} - {}", param.getOrderId(), response.getStringResult());
                }
            } else {
                param.setRemark(json.getString("message"));
                log.error("易宝分账完结请求失败! {} - {}", param.getOrderId(), response.getStringResult());
            }
        } catch (Exception e) {
            log.error("易宝分账完结请求异常! {}", param.getOrderId(), e);
        }
    }

    /**
     * 退款申请
     * @param orderId
     * @param outOrderNo
     * @param refundAmount
     */
    public void refund(String orderId, String outOrderNo, BigDecimal refundAmount) {
        YopRequest request = new YopRequest( "/rest/v1.0/trade/refund", "POST");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("orderId", orderId);
        request.addParameter("uniqueOrderNo", outOrderNo);
        request.addParameter("refundAmount", refundAmount);
        request.addParameter("refundRequestId", yeepayConfig.getUserPrefix()+IdUtils.fastSimpleUUID());
        try {
            YopResponse response = yeepayConfig.getClient().request(request);
            com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSON.parseObject(response.getStringResult());
            if ("OPR00000".equalsIgnoreCase(json.getString("code"))) {
                if ("SUCCESS".equalsIgnoreCase(json.getString("status"))) {
                    log.info("退款成功:{}|{}|{}。结果:{}", orderId, outOrderNo, refundAmount, json);
                } else {
                    log.info("退款失败:{}|{}|{}。结果:{}", orderId, outOrderNo, refundAmount, json);
                }
            } else {
                log.info("退款失败:{}|{}|{}。结果:{}", orderId, outOrderNo, refundAmount, json);
            }
        } catch (Exception e) {
            log.error("退款失败报错:{}|{}|{}。报错:{}", orderId, outOrderNo, refundAmount, e);
        }
    }

    /**
     * 退款查询
     */
    public void refundQuery(String orderId, String outOrderNo, String refundRequestId) {
        YopRequest request = new YopRequest( "/rest/v1.0/trade/refund/query", "GET");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("orderId", orderId);
        request.addParameter("refundRequestId", refundRequestId);
        try {
            YopResponse response = yeepayConfig.getClient().request(request);
            com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSON.parseObject(response.getStringResult());
            if ("OPR00000".equalsIgnoreCase(json.getString("code"))) {
                if ("SUCCESS".equalsIgnoreCase(json.getString("status"))) {
                    log.info("易宝退款查询成功! {} - {}", orderId, response.getStringResult());
                } else {
                    log.error("易宝退款查询失败! {} - {}", orderId, response.getStringResult());
                }
            } else {
                log.error("易宝退款查询请求失败! {} - {}", orderId, response.getStringResult());
            }
        } catch (Exception e) {
            log.error("易宝退款查询请求异常! {}", orderId, e);
        }
    }

    /**
     * 分账退还
     * @param t
     */
    public void divideReturn(YeePayDivideDto t) {
        YopRequest request = new YopRequest( "/rest/v1.0/divide/back", "POST");
        request.addParameter("parentMerchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("merchantNo", yeepayConfig.getMerchantNo());
        request.addParameter("orderId", t.getOrderNo());
        request.addParameter("uniqueOrderNo", t.getOutTradeNo());
        request.addParameter("returnAmount", t.getAmount());
        request.addParameter("divideRequestId", t.getRequestId());
        request.addParameter("divideBackRequestId", yeepayConfig.getUserPrefix()+IdUtils.fastSimpleUUID());
        Map<String, String> divideDetail = new HashMap<>();
        divideDetail.put("divideDetailNo", t.getDivideDetailNo());
        divideDetail.put("amount", t.getAmount().toPlainString());
        divideDetail.put("divideBackReason", "系统退款");
        List<Map<String, String>> list = new ArrayList<>();
        list.add(divideDetail);
        request.addParameter("divideBackDetail", com.alibaba.fastjson2.JSON.toJSONString(list));
        try {
            YopResponse response = yeepayConfig.getClient().request(request);
            com.alibaba.fastjson2.JSONObject json = com.alibaba.fastjson2.JSON.parseObject(response.getStringResult());
            if ("OPR00000".equalsIgnoreCase(json.getString("code"))) {
                if ("SUCCESS".equalsIgnoreCase(json.getString("status"))) {
                    log.info("易宝分账退回成功! {} - {}", t.getOrderId(), response.getStringResult());
                } else {
                    log.error("易宝分账退回失败! {} - {}", t.getOrderId(), response.getStringResult());
                }
            } else {
                log.error("易宝分账退回请求失败! {} - {}", t.getOrderId(), response.getStringResult());
            }
        } catch (Exception e) {
            log.error("易宝分账退回请求异常! {}", t.getOrderId(), e);
        }
    }
}
